package com.db4o.odbgen.plugins.java.database.id;

import java.util.ArrayList;
import java.util.List;


import com.db4o.internal.odbgen.StringUtils;
import com.db4o.internal.odbgen.plugins.java.database.DefaulValuetsXmlSchemaElement;
import com.db4o.internal.odbgen.plugins.java.database.id.IdXmlSchemaElement;
import com.db4o.odbgen.OdbgenException;
import com.db4o.odbgen.TargetLanguage;
import com.db4o.odbgen.plugins.MainGeneratorPlugin;
import com.db4o.odbgen.plugins.Plugin;
import com.db4o.odbgen.plugins.java.maingenerator.MainGenerator;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.DataType;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSClass;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSField;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSMethod;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSModifier;

/**
 * Adds ids to classes. 
 * @author liviu
 */
public class Id implements Plugin{

	private static String _idFieldName;
	private MainGenerator _mainGenerator;

	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public List<Class<? extends Plugin>> getPluginDependencies() {
		ArrayList<Class<? extends Plugin>> res = new ArrayList<Class<? extends Plugin>>();
		res.add(MainGenerator.class);
		return res;
	}

	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public void initialize(MainGeneratorPlugin mainGenerator) {
		this._mainGenerator = (MainGenerator)mainGenerator;
		
	}

	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public void start() throws OdbgenException {
		for(TSClass tsClass : this._mainGenerator.getTypedXmlSchema().getClasses()){
			//The class must belong to XmlSchema.
			if(tsClass.getElement()==null) continue;
			if(tsClass.getElement().getBooleanChildValue(IdXmlSchemaElement.ID.getName())){
				//Get id type.
				String idTypeString;
				if(tsClass.getElement().hasSingleChild(IdXmlSchemaElement.IDTYPE.getName())){
					idTypeString = tsClass.getElement().getSingleChild(IdXmlSchemaElement.IDTYPE.getName()).getContent();
				}
				else{
					idTypeString = IdXmlSchemaElement.IDTYPE.getDefaultValue();
				}
				IdType idType;
				try{
					idType = Enum.valueOf(IdType.class, idTypeString);
				}
				catch(IllegalArgumentException e){
					throw new OdbgenException("Unknown id type encountered: '%s'.", idTypeString);
				}
				
				//Get method name.
				String methodName;
				if(tsClass.getElement().hasSingleChild(IdXmlSchemaElement.IDMETHODNAME.getName())){
					methodName = tsClass.getElement().getSingleChild(IdXmlSchemaElement.IDMETHODNAME.getName()).getContent();
				}
				else{
					methodName = IdXmlSchemaElement.IDMETHODNAME.getDefaultValue();
				}

				//Generate the ids.
				if(idType == IdType.DB4OUUID){
					this.generateDb4oUuid(tsClass, methodName);
				}
				else if(idType == IdType.DB4OINTERNALID){
					this.generateDb4oInternalid(tsClass, methodName);
				}
				else{
					throw new OdbgenException("Unsupported id type encountered: '%s'.", idTypeString);
				}
			}
		}
	}


	/**
	 * Generates a native db4o uuid inside the specified class.
	 * @throws OdbgenException 
	 * @throws OdbgenException 
	 */
	private void generateDb4oUuid(TSClass tsClass, String methodName) throws OdbgenException {

		//Generate the transient field to hold the id.
		TSField idField = new TSField(
				null,
				TSModifier.getPrivateTransientModifier(),
				Id._idFieldName,
				new DataType("java.lang", "String", new ArrayList<DataType>())
				);
		
		//Generate the method to get the id.
		this._mainGenerator.getTypedXmlSchema().buildGetterMethod(
				tsClass, 
				idField, 
				TSModifier.getPublicModifier(), 
				methodName
				);

		//Generate the method to set the id.
		//This is an internal method.
		this._mainGenerator.getTypedXmlSchema().buildSetterMethod(
				tsClass, 
				idField, 
				TSModifier.getEmptyModifierList(), 
				methodName
				);
		
		//TODO: Generate the callback to fill the method.
		
	}

	private void generateDb4oInternalid(TSClass tsClass, String methodName) throws OdbgenException {
		// TODO Auto-generated method stub

	}
	
	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public boolean supportsTargetLanguage(TargetLanguage targetLanguage) {
		if(targetLanguage == TargetLanguage.JAVA){
			return true;
		}
		return false;
	}

}
